/*
 * telnet_raw.c
 *
 * 【终极·最终·纯净版】FreeRTOS Telnet Server
 * 适配 LwIP（无 flags 参数）
 * 解决：拼接、乱码、双重提示、编译错误
 */

#include "FreeRTOS.h"
#include "task.h"

#include "FreeRTOS_CLI.h"

#include "cli_command.h"
#include "net_cli_command.h"

#include "print_rtt.h"
#include <stdio.h>
#include <string.h>

#include "lwip/sockets.h"

// ==================== 配置 ====================
#define TELNET_PORT     23
#define TELNET_MAX_LINE 64
#define TELNET_USER     "root"
#define TELNET_PASS     "1234"

// ==================== Telnet 协议常量 ====================
#define IAC         255
#define DONT        254
#define DO          253
#define WONT        252
#define WILL        251
#define TELOPT_ECHO 1
#define TELOPT_SGA  3
int sock;
// ==================== 状态 ====================
typedef enum
{
  STATE_WAIT_USER,
  STATE_WAIT_PASS,
  STATE_LOGGED_IN
} telnet_state_t;

// ==================== 发送函数（适配 LwIP）====================
static void send_data(int sock, const char *str)
{
  if (str && *str)
  {
    send(sock, str, strlen(str), 0);
  }
}

static void send_p(int sock, const char *str)
{
  if (str && *str)
  {
    send(sock, str, strlen(str), 0);
    send(sock, "\r\n", 2, 0);
  }
}

static void send_prompt(int sock)
{
  send(sock, "\r\n", 2, 0);
  send_data(sock, "[root@DCDU ~]# ");
}

// ==================== 发送 IAC 命令宏 ====================
#define SEND_IAC(cmd, opt)                 \
  do                                       \
  {                                        \
    unsigned char buf[] = {IAC, cmd, opt}; \
    send(sock, buf, 3, 0);                 \
  } while (0)

// ==================== 处理客户端发来的 IAC ====================
static void handle_iac(unsigned char cmd, unsigned char opt, int sock)
{
  switch (cmd)
  {
  case WILL: // 客户端想开启某功能 → 拒绝
    if (opt == TELOPT_ECHO)
    {
      SEND_IAC(DONT, TELOPT_ECHO);
    }
    else
    {
      SEND_IAC(DONT, opt);
    }
    break;

  case DO: // 客户端让我开启某功能 → 拒绝
    if (opt == TELOPT_ECHO)
    {
      SEND_IAC(WONT, TELOPT_ECHO);
    }
    else
    {
      SEND_IAC(WONT, opt);
    }
    break;

  default:
    break;
  }
}
void vRegisterCLICommands(void)
{
  FreeRTOS_CLIRegisterCommand(&xMQTTCommand); /* 新增 MQTT */
  FreeRTOS_CLIRegisterCommand(&xSFPCommand);
  FreeRTOS_CLIRegisterCommand(&xVLANCommand);
  FreeRTOS_CLIRegisterCommand(&xNetworkCommand);
  FreeRTOS_CLIRegisterCommand(&xFactoryCommand);
  FreeRTOS_CLIRegisterCommand(&xRestartCommand);
  FreeRTOS_CLIRegisterCommand(&xEmptyLineCommand);
}
// ==================== 主任务 ====================
char output[1024];
void telnet_session_task(int sockets)
{
  char rx_buffer[64];
  char line[TELNET_MAX_LINE] = {0};
  int len = 0;
  telnet_state_t state = STATE_WAIT_USER;
  uint8_t auth_retry = 0;
  int iac_flag = 0; // 0=normal, 1=IAC, 2=IAC+CMD
  int last_was_newline = 0;
  sock = sockets;
  // 设置非阻塞
  int flags = fcntl(sock, F_GETFL, 0);
  fcntl(sock, F_SETFL, flags | O_NONBLOCK);
  // === 关键：不主动发任何 IAC！只响应 ===

  // 登录欢迎

  send_p(sock, "DCDU Telnet Server");
  {
    // ========== BOOTLOADER (0x8000313) ==========
    const char *bl_v = (const char *)0x08000313; // 'V' 地址 (确认: 0x8000313)
    char bl_ver[4] = {0};
    memcpy(bl_ver, bl_v + 1, 3); // 从 0x8000314 开始读 3 字节 → "0.1"
    bl_ver[3] = '\0';

    char bl_date[9] = {0};
    const char *raw_bl_date = bl_v + 5; // 0x8000318 开始
    snprintf(bl_date, sizeof(bl_date), "%c%c-%c%c-%c%c",
             raw_bl_date[0], raw_bl_date[1],  // YY
             raw_bl_date[2], raw_bl_date[3],  // MM
             raw_bl_date[4], raw_bl_date[5]); // DD

    // ========== APP (关键修正！) ==========
    const char *app_v = (const char *)0x800C313; // 'V' 地址 (确认: 0x800C313)

    char app_ver[6] = {0};
    memcpy(app_ver, app_v + 1, 5); // 从 0x800C313 读 5 字节 → "0.0.4"
    app_ver[5] = '\0';

    char app_date[18] = {0};
    const char *raw_app_date = app_v + 7; // 0x800C319 开始 (跳过 'V'+5 字符+下划线)
    snprintf(app_date, sizeof(app_date), "%c%c-%c%c-%c%c%c%c%c%c%c%c%c%c%c",
             raw_app_date[0], raw_app_date[1],
             raw_app_date[2], raw_app_date[3],
             raw_app_date[4], raw_app_date[5], //kk                  0         1              2                 3               4              5             6               7
             raw_app_date[6], raw_app_date[7], raw_app_date[8], raw_app_date[9], raw_app_date[10], raw_app_date[11], raw_app_date[12], raw_app_date[13], raw_app_date[14]);

    // ========== 最终输出 ==========
    char version_line[120];
    snprintf(version_line, sizeof(version_line),
             "Bootloader version: V%s 20%s   App version: V%s 20%s",
             bl_ver, bl_date, app_ver, app_date); // 注意: 这里是 V%s (app_ver 是 "0.0.4", 不是 "V0.0.4")

    send_p(sock, version_line);
  }

  send_data(sock, "Login: ");

  // 主循环
  while (1)
  {
    fd_set read_fds;
    struct timeval tv = {1, 0};
    FD_ZERO(&read_fds);
    FD_SET(sock, &read_fds);

    int activity = select(sock + 1, &read_fds, NULL, NULL, &tv);
    if (activity <= 0)
      continue;

    if (FD_ISSET(sock, &read_fds))
    {
      int n = recv(sock, rx_buffer, sizeof(rx_buffer), 0);
      if (n <= 0)
        break;
      //      LOG_INFO("telnet rec:%d", n);
      //      LOG_HEX(rx_buffer, n);
      for (int i = 0; i < n; i++)
      {
        unsigned char c = rx_buffer[i];
        // ✅ 关键：如果上一个字符是换行，且当前也是换行符，则跳过
        if (last_was_newline && (c == '\r' || c == '\n'))
        {
          last_was_newline = 0;
          continue; // 跳过 \n（如果是 \r\n 的第二部分）
        }
        // ✅ 重置换行标记（除非下面再次设置）
        if (c != '\r' && c != '\n')
        {
          last_was_newline = 0;
        }
        // 处理 IAC 协议
        if (iac_flag == 1)
        {
          if (c == IAC)
          {
            // 双 IAC 表示字面量 255
            if (len < TELNET_MAX_LINE - 1 && len >= 0)
            {
              line[len++] = c;
            }
            iac_flag = 0;
          }
          else
          {
            // 收到 IAC CMD OPT
            unsigned char cmd = c;
            if (++i >= n)
              break;
            unsigned char opt = rx_buffer[i];
            handle_iac(cmd, opt, sock);
            iac_flag = 0;
          }
        }
        else if (c == IAC)
        {
          iac_flag = 1;
        }
        else if (c == '\r' || c == '\n')
        {
          // ✅ 设置标记：本次是换行
          last_was_newline = 1;
          // 清理换行符
          while (len > 0 && (line[len - 1] == '\r' || line[len - 1] == '\n'))
          {
            len--;
          }

          if (len == 0)
          {
            if (state == STATE_LOGGED_IN)
            {
              send_prompt(sock);
            }
            continue;
          }
          line[len] = '\0';

          switch (state)
          {
          case STATE_WAIT_USER:
            if (strcmp(line, TELNET_USER) == 0)
            {
              send(sock, "\r\n", 2, 0);     // ✅ 显式换行
              send_data(sock, "Password:"); // ✅ 不用 send_p，避免自动加 \r\n
              state = STATE_WAIT_PASS;
            }
            else
            {
              send(sock, "\r\n", 2, 0);
              send_p(sock, "Login incorrect.");
              send_data(sock, "Login: ");
              auth_retry++;
              if (auth_retry >= 3)
                goto close;
            }
            break;
          case STATE_WAIT_PASS:
            if (strcmp(line, TELNET_PASS) == 0)
            {
              // send(sock, "\r\n", 2, 0);
              send_prompt(sock);
              state = STATE_LOGGED_IN;
            }
            else
            {
              send(sock, "\r\n", 2, 0);
              send_p(sock, "Login incorrect.");
              send_data(sock, "Password:");
              auth_retry++;
              if (auth_retry >= 3)
                goto close;
            }
            break;

          case STATE_LOGGED_IN:
          {
            
            for (;;)
            {
              BaseType_t more = FreeRTOS_CLIProcessCommand(line, output, sizeof(output));
              char *p = output + strlen(output);
              while (p > output + 2 && /* 至少留 \r\n */
                     (p[-1] == '\r' || p[-1] == '\n') &&
                     (p[-2] == '\r' || p[-2] == '\n'))
              {
                *--p = '\0';
              }
              send_data(sock, output); /* 立即发这一段 */
              if (more == pdFALSE)
                break; /* 没有下一段了 */
            }
            send_prompt(sock); // 再发一次 prompt（正常）
            break;
          }
          }
          len = 0;
          memset(line, 0, TELNET_MAX_LINE);
        }
        else if (c == '\b' || c == 127)
        {
          if (len > 0)
          {
            len--;
            send(sock, "\b \b", 3, 0);
          }
        }
        else if (c >= 32 && c < 127)
        {
          if (len < TELNET_MAX_LINE - 1)
          {
            if (state != STATE_WAIT_PASS)
            {
              send(sock, &c, 1, 0);
            }
            else
            {
              send(sock, "*", 1, 0);
            }
            line[len++] = c;
          }
        }
      }
    }
  }

close:
  send_p(sock, "\r\nGoodbye.");
  closesocket(sock);
}
